package com.darren.befriend.fragments;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.PowerManager;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.darren.befriend.BaseActivity;
import com.darren.befriend.HomeActivity;
import com.darren.befriend.R;
import com.darren.befriend.adapters.FriendsResultAdapter;
import com.darren.befriend.adapters.FriendsResultAdapter.OnFriendItemClickListener;
import com.darren.befriend.utilities.LogUtil;
import com.darren.befriend.utilities.Utilities;
import com.darren.befriend.views.CircleImageView;
import com.parse.ParseGeoPoint;
import com.parse.ParseObject;
import com.parse.ParsePush;
import com.parse.ParseQuery;
import com.parse.ParseUser;

public class HomeFragment extends Fragment implements OnRefreshListener,
		OnScrollListener {

	private final String TAG = "HomeFragment";
	public static ArrayList<ParseUser> mFriendArr;
	private final int STACK_SIZE = 30;
	private int mCurrentPage = 0;
	private boolean isMore = false;
	private View mFakeView;
	private TextView mFindingTv;
	private ListView mListview;
	private ParseUser mCurrentUsr;
	private ImageView mAnimationImg;
	private CircleImageView mFriendIcon;
	private FriendsResultAdapter mAdapter;
	private SwipeRefreshLayout mRefreshLayout;
	private RelativeLayout mSearchImageLayout;
	private OnFriendItemClickListener mListener;
	protected PowerManager.WakeLock mWakeLock;

	/**
	 * make instance HomeFragment with currentPage
	 * 
	 * @param currentPage
	 * @return
	 */
	public static HomeFragment makeInstance() {

		return new HomeFragment();
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {

		ViewGroup view = (ViewGroup) inflater.inflate(
				R.layout.layout_search_friend, container, false);
		mFriendIcon = (CircleImageView) view
				.findViewById(R.id.search_friend_icon);
		mRefreshLayout = (SwipeRefreshLayout) view
				.findViewById(R.id.home_refresh_layout);
		mSearchImageLayout = (RelativeLayout) view
				.findViewById(R.id.home_search_image_layout);
		mListview = (ListView) view.findViewById(R.id.home_listview);
		mFindingTv = (TextView) view.findViewById(R.id.search_friend_title);
		mAnimationImg = (ImageView) view.findViewById(R.id.search_friend_img);
		TextView friendNameTxt = (TextView) mListview
				.findViewById(R.id.friend_name);
		TextView friendAddTxt = (TextView) mListview
				.findViewById(R.id.friend_address);
		mRefreshLayout.setColorSchemeResources(R.color.white, R.color.white,
				R.color.white, R.color.white);
		mFakeView = (View) view.findViewById(R.id.home_search_fake_layout);
		Utilities.setFontType(getActivity(), friendAddTxt);
		Utilities.setFontType(getActivity(), friendNameTxt);
		mListview.setOnScrollListener(this);
		mRefreshLayout.setOnRefreshListener(this);
		return view;
	}

	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		if (getActivity() instanceof HomeActivity) {

			((HomeActivity) getActivity()).showTopLogo();
			((HomeActivity) getActivity())
					.setRightImage(R.drawable.icon_search);
			((HomeActivity) getActivity()).setLeftImage(R.drawable.icon_menu);
			((HomeActivity) getActivity()).showRightButtonImg(true);
			mCurrentUsr = ((HomeActivity) getActivity()).getCurrentUser();
			setProfileImage();
			if (mFriendArr == null) {

				mFriendArr = new ArrayList<ParseUser>();
				new SearchFriend().execute();
			} else {

				hideLoadingView();
				// if (mAdapter == null) {

				mAdapter = new FriendsResultAdapter(getActivity(), mFriendArr);
				mAdapter.setOnFriendClickListener(mListener);
				mListview.setAdapter(mAdapter);
				// } else {

				mAdapter.notifyDataSetChanged();
				// }
			}
		}
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		mListener = new OnFriendItemClickListener() {

			@Override
			public void ondislikeBack(int position, ParseUser user) {
				declineFriend(user);
				mFriendArr.remove(position);
				mAdapter.notifyDataSetChanged();
			}

			@Override
			public void onLikeBack(int position, ParseUser user) {
				acceptFriend(user);
				mFriendArr.remove(position);
				mAdapter.notifyDataSetChanged();
			}

			@Override
			public void onClick(int position, ParseUser user) {
				if (getActivity() == null)
					return;
				if (getActivity() instanceof HomeActivity) {
					UserInfoDetailFragment fragment = UserInfoDetailFragment
							.makeInstance(user, false, false, null);
					HomeActivity activity = (HomeActivity) getActivity();
					activity.switchContentWithNormalAnimation(fragment);
				}
			}
		};
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.support.v4.app.Fragment#onDestroy()
	 */
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub

		super.onDestroy();
	}

	@Override
	public void onRefresh() {

		isMore = false;
		mCurrentPage = 0;
		new SearchFriend().execute();
		mListview.setOnScrollListener(null);
		// mListview.completeRefreshing();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.widget.AbsListView.OnScrollListener#onScroll(android.widget.
	 * AbsListView, int, int, int)
	 */
	@Override
	public void onScroll(AbsListView view, int firstVisibleItem,
			int visibleItemCount, int totalItemCount) {
		// TODO Auto-generated method stub

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * android.widget.AbsListView.OnScrollListener#onScrollStateChanged(android
	 * .widget.AbsListView, int)
	 */
	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		// TODO Auto-generated method stub
		int threshold = 1;
		int count = mListview.getCount();

		if (scrollState == SCROLL_STATE_IDLE) {
			if ((mListview.getLastVisiblePosition() >= count - threshold)
					&& isMore) {
				mCurrentPage++;
				new SearchFriend().execute();
			}
		}
	}

	@SuppressWarnings("unchecked")
	public void declineFriend(ParseUser friend) {
		LogUtil.e(TAG, "declineFriend");
		ArrayList<String> array = (ArrayList<String>) mCurrentUsr.get("Enemy");
		boolean isFound = false;
		for (String element : array) {
			String[] usr = element.split("\\$\\$\\$");
			if (friend.getUsername().equals(usr[0])) {
				isFound = true;
			}
		}
		if (!isFound) {
			String object = new String();
			int currentTime = (int) new Date().getTime();
			object = String
					.format("%s$$$%d", friend.getUsername(), currentTime);
			array.add(object);
		}

		mCurrentUsr.put("Enemy", array);
		// mCurrentUsr.saveInBackground();
	}

	@SuppressWarnings("unchecked")
	public void acceptFriend(ParseUser friend) {

		LogUtil.e(TAG, "acceptFriend");
		ArrayList<String> array = (ArrayList<String>) mCurrentUsr
				.get("Friends");
		boolean isFound = false;
		for (String frd : array) {
			if (frd.equals(friend.getUsername())) {
				isFound = true;
			}
		}

		if (!isFound) {

			array.add(friend.getUsername());
		}

		mCurrentUsr.put("Friends", array);
		ArrayList<String> array1 = (ArrayList<String>) friend.get("Friends");
		isFound = false;
		for (String frd : array1) {
			if (frd.equals(mCurrentUsr.getUsername())) {
				isFound = true;
			}
		}

		if (!isFound) {
			ParseObject request = ParseObject.create("Requests");
			request.put("Sender", mCurrentUsr.getUsername());
			request.put("Receiver", friend.getUsername());
			request.put("Resolve", false);
			request.saveInBackground();
			String fullName = mCurrentUsr.getUsername();
			if (fullName.contains("_local")) {
				fullName = fullName.replace("_local", "");
			}
			String msg = String.format("%s send you friend request.", fullName);
			ParsePush push = new ParsePush();
			push.setChannel(String.format("CH_%s", friend.getUsername()));
			JSONObject data = null;
			try {
				data = new JSONObject("{\"alert\": \" " + msg
						+ "\",\"badge\": \"Increment\"}");
			} catch (JSONException e) {
				e.printStackTrace();
			}
			push.setData(data);
			push.setExpirationTimeInterval(86400);
			push.sendInBackground();
		}

		mCurrentUsr.saveInBackground();
	}

	public static void updateFriendList(ParseUser user) {
		// TODO Auto-generated method stub

		if (mFriendArr != null) {

			for (ParseUser currUser : mFriendArr) {

				if (currUser.getUsername().equals(user.getUsername())) {

					mFriendArr.remove(currUser);
					break;
				}
			}

		}
	}

	private void setProfileImage() {
		if (mCurrentUsr == null) {

			mFriendIcon.setImageResource(R.drawable.tmp_full_pic);
			return;
		}

		String fullName = "";
		try {

			fullName = mCurrentUsr.get("fullName").toString();
		} catch (Exception ex) {

		}

		if (fullName == null) {

			mFriendIcon.setImageResource(R.drawable.tmp_full_pic);
			return;
		}

		if (!fullName.contains("_local")) {

			String url = String.format(
					getResources().getString(R.string.profile_url),
					mCurrentUsr.getUsername());
			((HomeActivity) getActivity()).getImageLoader().displayImage(url,
					mFriendIcon, ((HomeActivity) getActivity()).getOptions());
		} else {

			Object imgData = mCurrentUsr.get("Photo");
			if (imgData == null) {

				mFriendIcon.setImageResource(R.drawable.tmp_full_pic);
			}
		}
	}

	/**
	 * show animation
	 */
	private void showLoadingView() {

		mFindingTv.setVisibility(View.VISIBLE);
		mSearchImageLayout.setVisibility(View.VISIBLE);
		mListview.setVisibility(View.INVISIBLE);
		mFakeView.setVisibility(View.VISIBLE);
		Animation animation = AnimationUtils.loadAnimation(getActivity(),
				R.anim.search_friend_animation);
		mAnimationImg.startAnimation(animation);
	}

	private void hideLoadingView() {

		Animation animation = mAnimationImg.getAnimation();
		mAnimationImg.clearAnimation();
		LogUtil.e("hideLoadingView", "hideLoadingView");
		if (animation != null) {

			LogUtil.e("animation", "animation");
			animation.cancel();
		}

		mFindingTv.setVisibility(View.INVISIBLE);
		mListview.setVisibility(View.VISIBLE);
		mSearchImageLayout.setVisibility(View.INVISIBLE);
		mFakeView.setVisibility(View.GONE);
	}

	/**
	 * check user is friend or not
	 * 
	 * @param username
	 * @return
	 */
	private boolean isUserFriend(String username) {

		@SuppressWarnings("unchecked")
		List<String> array = (List<String>) mCurrentUsr.get("Friends");
		if (array == null) {

			return false;
		}

		boolean result = false;
		for (String friendUsr : array) {
			if (username.equals(friendUsr)) {

				result = true;
				break;
			}
		}

		return result;
	}

	/**
	 * check user is enermy or not
	 * 
	 * @param username
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private boolean isUserEnemy(String username) {

		ArrayList<String> enemyArr = (ArrayList<String>) mCurrentUsr
				.get("Enemy");
		if (enemyArr == null) {

			return false;
		}

		boolean result = false;
		for (String enemyUsr : enemyArr) {

			String[] usr = enemyUsr.split("\\$\\$\\$");
			if (username.equals(usr[0])) {

				result = true;
				break;
			}
		}

		return result;
	}

	/**
	 * @param resultUser
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private boolean compareFilter(ParseUser resultUser, int pos) {

		ParseObject myFilter = (ParseObject) mCurrentUsr.get("Filter");
		if (myFilter == null) {

			LogUtil.e("Fecth Me Info", "myFilter null ");
			return false;
		}

		try {

			LogUtil.e("Fecth Me Info", "------------------ " + pos);
			resultUser.getParseObject("MeInfo").fetch();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			LogUtil.e("resultUser.getParseObject(MeInfo).fetchIfNeeded();",
					"Nullllllllll");
		}

		LogUtil.e("Fecth Me Info", "---------MeInfo--------- " + pos);
		ParseObject meInfo = (ParseObject) resultUser.get("MeInfo");
		if (meInfo == null) {

			return false;
		}

		// Age filter
		try {

			int startAge = (Integer) myFilter.get("StartAge");
			int endAge = (Integer) myFilter.get("EndAge");
			int myAge = (Integer) meInfo.get("MyAge");
			LogUtil.e("Fecth Me Info", "---------MyAge--------- " + startAge
					+ " --- " + myAge + " --- " + endAge);
			if (myAge <= startAge) {

				return false;
			}

			if (myAge > endAge && endAge < 41) {

				return false;
			}
		} catch (Exception ex) {

			return false;
		}

		LogUtil.e("Fecth Me Info", "---------Gender--------- " + pos);
		// Gender filter
		try {
			if (!(Boolean) myFilter.get("Men")
					&& (Integer) meInfo.get("Gender") == 0) {

				return false;
			}

			if (!(Boolean) myFilter.get("Women")
					&& (Integer) meInfo.get("Gender") == 1) {

				return false;
			}
		} catch (Exception ex) {

			LogUtil.e("Fecth Me Info", "---------Gender Error--------- ");
		}

		LogUtil.e("Fecth Me Info", "---------Child--------- " + pos);
		// Child filter
		try {
			if ((Integer) myFilter.get("Child") != null
					&& (Integer) myFilter.get("Child") == 1
					&& (Integer) meInfo.get("Children") == 0) {

				return false;
			}
		} catch (Exception ex) {

			return false;
		}

		LogUtil.e("Fecth Me Info", "---------Child--------- " + pos);
		if ((Integer) myFilter.get("Child") != null
				&& (Integer) myFilter.get("Child") == 2
				&& (Integer) meInfo.get("Children") != 0) {

			return false;
		}

		LogUtil.e("Fecth Me Info", "---------Money to burn--------- " + pos);
		// Money to burn
		int startMoney = (Integer) myFilter.get("StartMoney");
		int endMoney = (Integer) myFilter.get("EndMoney");
		if (endMoney > 1000) {

			if ((Integer) meInfo.get("MoneyToBurn") < startMoney) {

				return false;
			}
		} else {

			if (((Integer) meInfo.get("MoneyToBurn") < startMoney)
					|| ((Integer) meInfo.get("MoneyToBurn") > endMoney)) {

				return false;
			}
		}

		LogUtil.e("Fecth Me Info", "---------Interests--------- " + pos);
		// Interests
		{
			ArrayList<Boolean> interests = (ArrayList<Boolean>) mCurrentUsr
					.get("INTEREST");
			if (interests != null) {

				boolean isSet = false;
				for (int i = 0; i < interests.size(); i++) {

					if (interests.get(i)) {

						isSet = true;
						break;
					}
				}

				if (isSet) {
					boolean result = false;
					ArrayList<Boolean> interests1 = (ArrayList<Boolean>) resultUser
							.get("INTEREST");
					if (interests1 != null) {

						for (int i = 0; i < 40; i++) {

							try {
								boolean num1, num2;
								num1 = interests.get(i);
								num2 = interests1.get(i);
								if (num1 == num2 && num1 && num2) {
									result = true;
									break;
								}
							} catch (Exception ex) {

								result = false;
								break;
							}
						}

						if (!result) {

							return result;
						}
					}
				}
			}
		}

		LogUtil.e("Fecth Me Info", "---------Sports--------- " + pos);
		// Sports
		{
			ArrayList<Boolean> sports = (ArrayList<Boolean>) mCurrentUsr
					.get("SPORTS");
			if (sports != null) {

				boolean isSet = false;
				for (int i = 0; i < sports.size(); i++) {

					if (sports.get(i)) {

						isSet = true;
						break;
					}
				}

				if (isSet) {
					boolean result = false;
					ArrayList<Boolean> sports1 = (ArrayList<Boolean>) resultUser
							.get("SPORTS");
					if (sports1 != null) {

						for (int i = 0; i < 48; i++) {

							try {
								boolean num1, num2;
								num1 = sports.get(i);
								num2 = sports1.get(i);
								if (num1 == num2 && num1 && num2) {
									result = true;
									break;
								}
							} catch (Exception ex) {

								result = false;
								break;
							}
						}

						if (!result) {

							return result;
						}
					}
				}
			}
		}

		LogUtil.e("Fecth Me Info", "---------films--------- " + pos);
		// films
		{
			ArrayList<Boolean> films = (ArrayList<Boolean>) mCurrentUsr
					.get("FILMS");
			if (films != null) {

				boolean isSet = false;
				for (int i = 0; i < films.size(); i++) {

					if (films.get(i)) {

						isSet = true;
						break;
					}
				}

				if (isSet) {
					boolean result = false;
					ArrayList<Boolean> films1 = (ArrayList<Boolean>) resultUser
							.get("FILMS");
					if (films1 != null) {

						for (int i = 0; i < 25; i++) {

							try {
								boolean num1, num2;
								num1 = films.get(i);
								num2 = films1.get(i);
								if (num1 == num2 && num1 && num2) {

									result = true;
									break;
								}
							} catch (Exception ex) {

								result = false;
								break;
							}
						}

						if (!result) {

							return result;
						}
					}
				}
			}
		}

		LogUtil.e("Fecth Me Info", "---------Music--------- " + pos);
		// Music
		try {
			ArrayList<Boolean> music = (ArrayList<Boolean>) mCurrentUsr
					.get("MUSIC");
			if (music != null) {

				boolean isSet = false;
				for (int i = 0; i < music.size(); i++) {

					if (music.get(i)) {

						isSet = true;
						break;
					}
				}

				if (isSet) {
					boolean result = false;
					ArrayList<Boolean> music1 = (ArrayList<Boolean>) resultUser
							.get("MUSIC");
					if (music1 != null) {

						for (int i = 0; i < 31; i++) {

							try {
								boolean num1, num2;
								num1 = music.get(i);
								num2 = music1.get(i);
								if (num1 == num2 && num1 && num2) {
									result = true;
									break;
								}
							} catch (Exception ex) {

								result = false;
								break;
							}
						}

						if (!result) {

							return result;
						}
					}
				}
			}
		} catch (Exception ex) {

			ex.printStackTrace();
		}

		LogUtil.e("Fecth Me Info", "---------Personality--------- " + pos);
		// Personality
		{
			List<Boolean> personality = (List<Boolean>) myFilter
					.get("Personality");
			if (personality != null) {

				boolean isSet = false;
				for (int i = 0; i < personality.size(); i++) {

					if (personality.get(i)) {

						isSet = true;
						break;
					}
				}

				if (isSet) {
					boolean tmp = personality.get((Integer) meInfo
							.get("Personality"));
					if (!tmp) {

						return false;
					}
				}
			}
		}

		LogUtil.e("Fecth Me Info", "---------hobbies--------- " + pos);
		// hobbies
		{
			ParseObject myMeInfo = (ParseObject) mCurrentUsr.get("MeInfo");
			if (myMeInfo == null) {

				return false;
			}

			List<Boolean> hobby = (List<Boolean>) myMeInfo.get("Hobby");
			if (hobby != null) {

				boolean isSet = false;
				for (int i = 0; i < hobby.size(); i++) {

					if (hobby.get(i)) {

						isSet = true;
						break;
					}
				}

				if (isSet) {
					List<Boolean> hobby1 = (List<Boolean>) meInfo.get("Hobby");
					if (hobby1 != null) {
						boolean result = false;
						for (int i = 0; i < 9; i++) {

							try {
								boolean val1, val2;
								val1 = hobby.get(i);
								val2 = hobby1.get(i);
								if (val1 == val2 && val1 && val2) {

									result = true;
								}
							} catch (Exception ex) {

								result = false;
								break;
							}
						}

						return result;
					}
				}
			}
		}

		return true;
	}

	private class SearchFriend extends AsyncTask<Void, Void, List<ParseUser>> {

		@SuppressWarnings("deprecation")
		@Override
		protected void onPreExecute() {
			super.onPreExecute();

			mRefreshLayout.setRefreshing(false);
			showLoadingView();
			final PowerManager pm = (PowerManager) getActivity()
					.getSystemService(Context.POWER_SERVICE);
			mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,
					"My Tag");
			((HomeActivity) getActivity()).setLock(true);
			mWakeLock.acquire();
		}

		@Override
		protected List<ParseUser> doInBackground(Void... params) {

			ParseGeoPoint userGeoPoint = (ParseGeoPoint) mCurrentUsr
					.get("Position");
			if (userGeoPoint == null) {

				if (BaseActivity.mGeoPoint != null) {

					userGeoPoint = BaseActivity.mGeoPoint;
				}
			}

			List<ParseUser> searchUsers = new ArrayList<ParseUser>();

			// create query for places
			ParseQuery<ParseUser> query = ParseUser.getQuery();
			if (userGeoPoint != null) {

				query.whereNear("Position", userGeoPoint);
				// query.whereWithinMiles("Position", userGeoPoint, 10000000);
			} else {

				LogUtil.e("Can't access your location",
						"Can access your location");
			}

			query.setSkip(mCurrentPage * STACK_SIZE);
			query.setLimit(STACK_SIZE);
			try {

				List<ParseUser> results = query.find();
				if (results.size() == STACK_SIZE) {

					isMore = true;
				} else {

					isMore = false;
				}

				for (int i = 0; i < results.size(); i++) {

					ParseUser user = (ParseUser) results.get(i);
					if (user.getUsername().equals(mCurrentUsr.getUsername())) {

						continue;
					}

					if (isUserFriend(user.getUsername())) {

						continue;
					}

					if (isUserEnemy(user.getUsername())) {

						continue;
					}

					if (compareFilter(user, i)) {

						searchUsers.add(user);
					}
				}
			} catch (Exception e) {

			}

			return searchUsers;
		}

		@Override
		protected void onPostExecute(List<ParseUser> result) {
			super.onPostExecute(result);

			try {

				mWakeLock.release();
			} catch (Exception ex) {

				LogUtil.e("mWakeLock.release()", ex.getMessage());
			}

			hideLoadingView();
			if (getActivity() == null) {

				return;
			}

			// Clear friend list if reload
			if (mCurrentPage == 0) {

				mAdapter = null;
				mListview.setAdapter(mAdapter);
				if (mFriendArr != null) {

					mFriendArr.clear();
				}
			}

			if (result != null && mFriendArr != null) {

				mFriendArr.addAll(result);
			}

			if (mAdapter == null || mCurrentPage == 0) {

				mAdapter = new FriendsResultAdapter(getActivity(), mFriendArr);
				mAdapter.setOnFriendClickListener(mListener);
				mListview.setAdapter(mAdapter);
			} else {

				mAdapter.notifyDataSetChanged();
			}

			((HomeActivity) getActivity()).setLock(false);
			// mListview.completeRefreshing();
			mListview.setOnScrollListener(HomeFragment.this);
			// FriendSearchResultFragment fragment = FriendSearchResultFragment
			// .create(mFriends, isMore, mCurrentPage);
			// HomeActivity act = (HomeActivity) getActivity();
			// act.switchContent(fragment);
		}
	}

}
